//
// Created by Yun on 2025/3/2.
//

#include "dev_oled_4p.h"

static uint8_t Dev_OLed_4P_Write_Multiple_Cmd(Dev_OLed_4p_Cfg_TypeDef* pstDevOLed4PCfg,
                                     uint8_t* pu8Data, uint16_t u16Len)
{
    uint8_t u8Data[256] = {pstDevOLed4PCfg->u8CmdMem};
    memcpy(u8Data+1, pu8Data, u16Len);

    CHECK_DEV_STATUS(pstDevOLed4PCfg->pstI2CInterface->Transmit(pstDevOLed4PCfg->pHwCfg,
                                                                pstDevOLed4PCfg->u16DevAddr,
                                                                u8Data,
                                                                u16Len + 1,
                                                                pstDevOLed4PCfg->u16TimeOut));
    return DEV_OK;
}

static uint8_t Dev_OLed_4P_Write_Multiple_Data(Dev_OLed_4p_Cfg_TypeDef* pstDevOLed4PCfg,
                                               uint8_t* pu8Data, uint16_t u16Len)
{
    uint8_t u8Data[256] = {pstDevOLed4PCfg->u8DataMem};
    memcpy(u8Data+1, pu8Data, u16Len);

    CHECK_DEV_STATUS(pstDevOLed4PCfg->pstI2CInterface->Transmit(pstDevOLed4PCfg->pHwCfg,
                                                                pstDevOLed4PCfg->u16DevAddr,
                                                                u8Data,
                                                                u16Len + 1,
                                                                pstDevOLed4PCfg->u16TimeOut));
    return DEV_OK;
}

uint8_t Dev_OLed_4P_Register(Dev_OLed_4p_Cfg_TypeDef* pstDevOLed4PCfg,
                             void* pHwCfg,
                             I2c_Interface_TypeDef* pstI2CInterface)
{

    if(pHwCfg == NULL || pstDevOLed4PCfg->pu8InitCmd == NULL
    || pstDevOLed4PCfg->u16InitCmdLen == 0 ||
        pstDevOLed4PCfg->u16DevAddr == 0x00) return DEV_ERROR;

    DEV_UN_INIT(pstDevOLed4PCfg);

    pstDevOLed4PCfg->pstI2CInterface = pstI2CInterface;
    pstDevOLed4PCfg->pHwCfg = pHwCfg;

    /* I2C接口初始化 */
    CHECK_DEV_STATUS(pstDevOLed4PCfg->pstI2CInterface->Init(pHwCfg));

    DEV_INIT(pstDevOLed4PCfg);

    /* 屏幕初始化 */
    Dev_OLed_4P_Write_Multiple_Cmd(pstDevOLed4PCfg,
                                   pstDevOLed4PCfg->pu8InitCmd,
                                   pstDevOLed4PCfg->u16InitCmdLen);

    /* 开启显示 */
    Dev_OLed_4P_Display_En(pstDevOLed4PCfg,1);

    /* 清屏 */
    Dev_OLed_4P_Clear(pstDevOLed4PCfg);

    return DEV_OK;
}


uint8_t Dev_OLed_4P_Display_En(Dev_OLed_4p_Cfg_TypeDef* pstDevOLed4PCfg,uint8_t u8Enable)
{
    CHECK_DEV_ENABLE(pstDevOLed4PCfg);
    DEV_BUSY(pstDevOLed4PCfg);

    uint8_t u8Cmd[3]= {OLED_SET_DCDC,0x00,0x00};
    if(u8Enable > 0)
    {
        u8Cmd[1] = OLED_SET_DCDC_ON;
        u8Cmd[2] = OLED_DISPLAY_ON;
    }
    else
    {
        u8Cmd[1] = OLED_SET_DCDC_OFF;
        u8Cmd[2] = OLED_DISPLAY_OFF;
    }

    Dev_OLed_4P_Write_Multiple_Cmd(pstDevOLed4PCfg,
                                   u8Cmd,
                                   sizeof(u8Cmd));
    return DEV_OK;
}

uint8_t Dev_OLed_4P_Clear(Dev_OLed_4p_Cfg_TypeDef* pstDevOLed4PCfg)
{
    CHECK_DEV_ENABLE(pstDevOLed4PCfg);
    DEV_BUSY(pstDevOLed4PCfg);

    uint8_t u8Cmd[3]= {0x00,0x00,0x10};
    uint8_t u8Data[128] = {0x00};

    uint8_t i;
    for(i=0;i<8;i++)
    {
        u8Cmd[0] = 0xB0+i;
        Dev_OLed_4P_Write_Multiple_Cmd(pstDevOLed4PCfg,
                                       u8Cmd,
                                       sizeof(u8Cmd));

        Dev_OLed_4P_Write_Multiple_Data(pstDevOLed4PCfg,u8Data,sizeof(u8Data));
    } //更新显示

    return DEV_OK;
}


// 设置坐标函数优化
static uint8_t Dev_OLed_4P_Set_Pos(Dev_OLed_4p_Cfg_TypeDef* pstDevOLed4PCfg,
                                   uint8_t u8PosX,
                                   uint8_t u8PosY)
{

    uint8_t u8Cmd[3]= {0x00,0x00,0x00};

    u8Cmd[0] = 0xB0+u8PosY;
    u8Cmd[1] = ((u8PosX&0xf0)>>4)|0x10;
    u8Cmd[2] = u8PosX&0x0f;
    Dev_OLed_4P_Write_Multiple_Cmd(pstDevOLed4PCfg,
                                   u8Cmd,
                                   sizeof(u8Cmd));
    return DEV_OK;
}


uint8_t Dev_OLed_4P_Show(Dev_OLed_4p_Cfg_TypeDef* pstDevOLed4PCfg,
                         uint8_t u8PosX,
                         uint8_t u8PosY,
                         uint8_t* pu8Data,
                         uint16_t u16Width,
                         uint16_t u16Height)
{
    CHECK_DEV_ENABLE(pstDevOLed4PCfg);
    DEV_BUSY(pstDevOLed4PCfg);

    // 参数校验增强版
    if(!pstDevOLed4PCfg || !pu8Data) return DEV_ERROR;
    if((u8PosX >= 128) || (u8PosY >= 64) ||
       (u8PosX + u16Width > 128) || (u8PosY + u16Height > 64) ||
       (u16Width == 0) || (u16Height == 0))
        return DEV_ERROR;

    // 计算分页参数
    uint8_t u8Bits = u8PosY % 8;
    uint16_t u16StartPage = u8PosY / 8;
    uint16_t u16EndPage = u16StartPage +  (u8Bits+u16Height)/ 8;
//    if(u16Height%8 != 0) u16EndPage++;

    // 逐页处理
    for(uint16_t u16Page = u16StartPage; u16Page < u16EndPage; u16Page++)
    {

        if(u8Bits == 0)
        {
            /* 设置显示位置并写入数据 */
            Dev_OLed_4P_Set_Pos(pstDevOLed4PCfg, u8PosX, u16Page);
            Dev_OLed_4P_Write_Multiple_Data(pstDevOLed4PCfg,
                                            pu8Data+(u16Page-u16StartPage)*u16Width,
                                            u16Width);
            continue;
        }

        uint8_t u8Data[128] = {0x00};

        /* 跨行处理 */
        for(uint16_t i = 0; i < u16Width; i++)
        {
            /* 计算当前位 */
            uint8_t u8Tmp = *(pu8Data+(u16Page-u16StartPage)*u16Width + i);

            if(u16Page == u16StartPage)
            {
                u8Data[i] = u8Tmp>>u8Bits;
            }
            else
            {
                /* 计算上一行对应位 */
                uint8_t u8Tmp1 = *(pu8Data+(u16Page- u16StartPage -1)*u16Width + i);
                u8Data[i] = (u8Tmp1<<(8-u8Bits))|(u8Tmp>>u8Bits);
            }
        }

        /* 设置显示位置并写入数据 */
        Dev_OLed_4P_Set_Pos(pstDevOLed4PCfg, u8PosX, u16Page);
        Dev_OLed_4P_Write_Multiple_Data(pstDevOLed4PCfg,
                                        u8Data,
                                        u16Width);
    }

    // 末行处理
    if((u8PosY+u16Height) % 8 != 0)
    {
        uint8_t u8Data[128] = {0x00};

        for(uint16_t i = 0; i < u16Width; i++)
        {
            uint8_t u8Tmp = *(pu8Data+(u16EndPage-u16StartPage)*u16Width + i);
            u8Data[i] = (u8Tmp<<u8Bits)|(0x00>>(8-u8Bits));
        }

        Dev_OLed_4P_Set_Pos(pstDevOLed4PCfg, u8PosX, u16EndPage);
        Dev_OLed_4P_Write_Multiple_Data(pstDevOLed4PCfg,
                                        u8Data,
                                        u16Width);
    }

    return DEV_OK;
}
